import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreatePostDto } from './dto/create-post.dto';
import { PrismaService } from 'src/prisma/prisma.service';
import { RedisService } from 'src/redis/redis.service';
import { console } from 'inspector';

@Injectable()
export class PostService {
  constructor(
    private readonly prismaService: PrismaService,
    private readonly redisService: RedisService,
  ) {}
  async create(createPostDto: CreatePostDto, userId: number) {
    try {
      return await this.prismaService.post.create({
        data: {
          title: createPostDto.title,
          content: createPostDto.content,
          img: createPostDto.img,
          userId: userId,
          categoryId: +createPostDto.categoryId,
        },
      });
    } catch (error) {
      console.log(error);
      console.log('error', error);
      throw new HttpException(error.message, HttpStatus.BAD_REQUEST);
    }
  }

  async findAll(categoryId: number, page = 1, limit = 10, keyword?: string) {
    try {
      const whereCondition: any = {
        categoryId: +categoryId,
      };

      if (keyword) {
        whereCondition.OR = [
          {
            title: {
              contains: keyword,
            },
          },
          {
            content: {
              contains: keyword,
            },
          },
        ];
      }

      const list = await this.prismaService.post.findMany({
        include: {
          User: {
            select: {
              username: true,
              avatar: true,
            },
          },
        },
        where: whereCondition,
        skip: (page - 1) * limit,
        take: limit,
      });

      const total = await this.prismaService.post.count({
        where: whereCondition,
      });

      return { list, total };
    } catch (error) {
      throw new HttpException(error, HttpStatus.BAD_REQUEST);
    }
  }

  async getCategoryList() {
    try {
      return await this.prismaService.category.findMany();
    } catch (error) {
      throw new HttpException(error, HttpStatus.BAD_REQUEST);
    }
  }

  async getPostDetail(id: number) {
    try {
      return await this.prismaService.post.findUnique({
        where: {
          id: +id,
        },
        include: {
          User: {
            select: {
              username: true,
              avatar: true,
              id: true,
            },
          },
          Support: true,
        },
      });
    } catch (error) {
      throw new HttpException(error, HttpStatus.BAD_REQUEST);
    }
  }

  async readNum(id: number, userId: number) {
    const res = await this.redisService.hashGet('post_' + id);

    if (!res.readNum) {
      const post = await this.prismaService.post.findUnique({
        where: {
          id,
        },
      });
      await this.prismaService.post.update({
        where: {
          id: +id,
        },
        data: {
          readNum: +post.readNum + 1,
        },
      });
      await this.redisService.hashSet('post_' + id, {
        readNum: +post.readNum + 1,
        support: +post.support + 0,
        star: +post.star + 0,
      });

      await this.redisService.set(`user_${userId}post_${id}`, '1', 10 * 60);

      return +post.readNum + 1;
    } else {
      const flag = await this.redisService.get(`user_${userId}post_${id}`);
      if (!flag) {
        await this.redisService.hashSet('post_' + id, {
          readNum: +res.readNum + 1,
          support: +res.likeNum + 0,
          star: +res.commentNum + 0,
        });
        await this.redisService.set(`user_${userId}post_${id}`, '1', 10 * 60);
      } else {
        return +res.readNum;
      }
    }
  }

  // 点赞
  async support(id: number, userId: number) {
    try {
      const res = await this.redisService.hashGet('post_' + id);

      if (!res.support) {
        const post = await this.prismaService.post.findUnique({
          where: {
            id,
          },
        });

        await this.prismaService.post.update({
          where: {
            id: +id,
          },
          data: {
            support: +post.support + 1,
          },
        });
        await this.redisService.hashSet('post_' + id, {
          readNum: +post.readNum + 0,
          support: +post.support + 1,
          star: +post.star + 0,
        });

        await this.redisService.set(`user_${userId}_post_${id}_support`, '1');

        return +post.support + 1;
      } else {
        const flag = await this.redisService.get(
          `user_${userId}_post_${id}_support`,
        );
        if (!flag) {
          await this.redisService.hashSet('post_' + id, {
            readNum: +res.readNum + 0,
            support: +res.support + 1,
            star: +res.commentNum + 0,
          });

          await this.redisService.set(`user_${userId}_post_${id}_support`, '1');
        } else {
          return +res.support;
        }
      }
    } catch (error) {
      throw new HttpException(error, HttpStatus.BAD_REQUEST);
    }
  }

  // 取消点赞
  async cancelSupport(id: number, userId: number) {
    try {
      const res = await this.redisService.hashGet('post_' + id);

      if (!res.support) {
        const post = await this.prismaService.post.findUnique({
          where: {
            id,
          },
        });

        if (post.support <= 0) {
          return +post.support;
        }

        await this.prismaService.post.update({
          where: {
            id: +id,
          },
          data: {
            support: +post.support - 1,
          },
        });
        await this.redisService.hashSet('post_' + id, {
          readNum: +post.readNum + 0,
          support: +post.support - 1,
          star: +post.star + 0,
        });

        await this.redisService.set(
          `user_${userId}_post_${id}_support_del`,
          '0',
        );

        return +post.support - 1;
      } else {
        const flag = await this.redisService.get(
          `user_${userId}_post_${id}_support`,
        );
        if (!flag) {
          return +res.support;
        } else {
          await this.redisService.hashSet('post_' + id, {
            readNum: +res.readNum + 0,
            support: +res.support - 1,
            star: +res.star + 0,
          });
          await this.redisService.del(`user_${userId}_post_${id}_support`);
          await this.redisService.set(
            `user_${userId}_post_${id}_support_del`,
            '0',
          );
          return +res.support - 1;
        }
      }
    } catch (error) {
      throw new HttpException(error, HttpStatus.BAD_REQUEST);
    }
  }

  // 点赞表的入库
  async supToRedis() {
    const sup_keys = await this.redisService.getKeys('user_*_post_*_support');
    if (sup_keys.length === 0) return;

    for (let i = 0; i < sup_keys.length; i++) {
      const item = sup_keys[i];
      const [, userId, , postId] = item.split('_');
      process.stdout.write(postId + 'postId');
      const support = await this.prismaService.support.findFirst({
        where: {
          postId: +postId,
          userId: +userId,
        },
      });
      if (support) return;
      await this.prismaService.support.create({
        data: {
          userId: +userId,
          postId: +postId,
        },
      });
    }

    const sup_keys_del = await this.redisService.getKeys(
      'user_*_post_*_support_del',
    );

    if (sup_keys_del.length === 0) return;

    for (let i = 0; i < sup_keys_del.length; i++) {
      const item = sup_keys_del[i];
      const [, userId, , postId] = item.split('_');
      const support = await this.prismaService.support.findFirst({
        where: {
          postId: +postId,
          userId: +userId,
        },
      });
      if (!support) return;
      await this.prismaService.support.delete({
        where: {
          id: support.id,
        },
      });
    }
  }

  async saveToDb() {
    const res = await this.redisService.getKeys('post_*');
    if (res.length === 0) {
      return;
    }
    res.forEach(async (item) => {
      const [, id] = item.split('_');
      await this.prismaService.post.update({
        where: {
          id: +id,
        },
        data: {
          readNum: +(await this.redisService.hashGet(item)).readNum,
          support: +(await this.redisService.hashGet(item)).support,
          star: +(await this.redisService.hashGet(item)).star,
        },
      });
    });
  }
}
